#include "Widget.h"
#include "Manager.h"
#include "../ImageManager.h"

extern bool Collision(const core::Rectangle& A, const core::Rectangle& B);

namespace PickinOpenSticks {
    namespace Ui {

        /**
         * AddWidget: Adds a child widget to the current widget
         * @param const string& name - The name of the widget(for later access)
         * @param Widget* widget- the widget you want added
         * @date 21/10/2010
         */
        void Widget::AddWidget(Widget *child) {
            if (child) {
                child->SetParent(this);
                ui.insert(std::make_pair<int, Widget*>(++index, child));
            }
        }

        /**
         * Draw: Renders the widget on screen
         * @param RenderTarget* target - the rendering target
         * @date 21/10/2010
         */
        void Widget::Draw(sf::RenderTarget* target) {
            if (!visible) return;

            //the draw widget
            if (mainVisible) target->Draw(sprite);

            //then draw it's child widgets
            for (WidgetList::iterator itr = ui.begin(); itr != ui.end(); itr++) {
                itr->second->Draw(target);
            }
        }

        /**
         * SetDefaultImage: Initializes the widget with the default values
         * @date 29/10/2010
         */
        void Widget::SetDefaultImage() {
            sf::Image image;
            image.Create(200, 100, sf::Color(236, 233, 216)); //grayish color
            sprite.SetImage(ImageManager::GetSingleton().GetImage(image, "basic_widget"));
            pos.Setup(0, 0, sprite.GetImage()->GetWidth(), sprite.GetImage()->GetHeight());
            sprite.SetPosition(0, 0);
        }

        /**
         * Update: Updates the widget and it's child widgets
         * @param int diff - Time passed since last update
         * @date 21/10/2010
         */
        void Widget::Update(int diff) {
            if (!visible) return;

            /* Reset every update variables */


            //if the widget has child widgets
            if (ui.size() > 0) {
                for (int i = 0; i < (int) events.size(); i++) {
                    sf::Event* event = events[i];
                    switch (event->Type) {
                        case sf::Event::MouseButtonPressed:
                            for (WidgetList::iterator itr = ui.begin(); itr != ui.end(); itr++) {
                                int x = events[i]->MouseButton.X;
                                int y = events[i]->MouseButton.Y;
                                sf::Vector2f v = Manager::GetSingleton().ConvertCoords(x, y);
                                x = v.x;
                                y = v.y;
                                if (Collision(core::Rectangle(x, y, 2, 2), itr->second->GetPos())) {
                                    //some child widget was click.. call the handler function
                                    OnChildEvent(itr->second, event, true);
                                    focus = itr->second;
                                    //focus->RegisterEvent(event);
                                }
                            }
                            break;
                        case sf::Event::MouseButtonReleased:
                            if (focus) {
                                sf::Vector2f pos = Manager::GetSingleton().ConvertCoords(event->MouseButton.X, event->MouseButton.Y);
                                if (Collision(core::Rectangle(pos, sf::Vector2f(2, 2)), focus->GetPos())) {
                                    OnChildEvent(focus, event, true);
                                    //focus->RegisterEvent(event);		
                                } else {
                                    OnChildEvent(focus, event);
                                    //focus->RegisterEvent(event);	
                                }
                            }
                            break;
                        default:
                            OnChildEvent(focus, event);
                            //if(focus) focus->RegisterEvent(event);
                            break;
                    }
                }
            } else {
                for (unsigned int i = 0; i < events.size(); i++) {
                    sf::Event* event = events[i];
                    switch (event->Type) {
                        case sf::Event::MouseButtonPressed: OnClickPressed(event);
                            break;
                        case sf::Event::MouseButtonReleased:OnClickReleased(event);
                            break;
                        case sf::Event::KeyPressed: OnKeyPressed(event);
                            break;
                        case sf::Event::KeyReleased:OnKeyReleased(event);
                            break;
                        case sf::Event::TextEntered: OnTextEntered(event);
                            break;
                        default: OnOtherEvents(event);
                            break;
                    }
                }
            }
            //we solved events..so clear them
            events.clear();

            //now check for child events
            for (WidgetList::iterator i = ui.begin(); i != ui.end(); i++) {
                i->second->Update(diff);
            }
        }

        Widget* Widget::FindChildByName(const std::string& name) {
            for (WidgetList::iterator itr = ui.begin(); itr != ui.end(); itr++) {
                if (itr->second->GetName() == name)
                    return itr->second;
            }

            return 0;
        }

        void Widget::HideChildren() {
            for (WidgetList::iterator i = ui.begin(); i != ui.end(); i++) {
                i->second->Hide();
            }
        }

        void Widget::ShowChildren() {
            for (WidgetList::iterator i = ui.begin(); i != ui.end(); i++) {
                i->second->Show();
            }
        }

        void Widget::RegisterEvent(sf::Event* event) {
            if (visible) events.push_back(event);
        }

        void Widget::OnChildEvent(Widget* child, sf::Event* event, bool collided) {
            if (!child) {
                cerr << "OnChildEvent() - error - child is NULL! -ignoring event!" << endl;
                return;
            }
            switch (event->Type) {
                case sf::Event::MouseButtonPressed: OnChildClickPressed(child, event, collided);
                    break;
                case sf::Event::MouseButtonReleased:OnChildClickReleased(child, event, collided);
                    break;
                case sf::Event::KeyPressed: OnChildKeyPressed(child, event);
                    break;
                case sf::Event::KeyReleased:OnChildKeyReleased(child, event);
                    break;
                case sf::Event::TextEntered: OnChildTextEntered(child, event);
                    break;
                default: OnChildOtherEvents(child, event);
                    break;
            }
        }
    }
}
